use criterion::{criterion_group, criterion_main, Criterion, black_box};
use std::io::{Write, Read, Seek};
use tempfile::tempfile;
use tokio::runtime::Runtime;
use tokio::io::{AsyncWriteExt, AsyncReadExt, AsyncSeekExt};
// This is a struct that tells Criterion.rs to use the "futures" crate's current-thread executor
//use criterion::async_executor::FuturesExecutor;

fn read_write_tempfile_benchmark(file_size: usize) {
    let mut file = tempfile().unwrap();

    let data = vec![0u8; file_size];
    file.write_all(&data).unwrap();
    file.sync_all().unwrap();

    let mut read_data = vec![0u8; file_size];
    file.seek(std::io::SeekFrom::Start(0)).unwrap();
    file.read_exact(&mut read_data).unwrap();
}

async fn tokio_async_io_read_write_benchmark(file_size: usize) {
    let mut file = tokio::fs::File::from_std(tempfile().unwrap());

    let data = vec![0u8; file_size];
    file.write_all(&data).await.unwrap();
    file.sync_all().await.unwrap();

    let mut read_data = vec![0u8; file_size];
    file.seek(tokio::io::SeekFrom::Start(0)).await.unwrap();
    file.read_exact(&mut read_data).await.unwrap();
}

fn benchmark(c: &mut Criterion) {
    let file_size = 1024 * 1024; // 1 MB

    c.bench_function("std write_read", |b| b.iter(|| read_write_tempfile_benchmark(black_box(file_size))));

    let rt = Runtime::new().unwrap();
    c.bench_function("tokio write_read", |b| {
        b.to_async(&rt).iter(|| tokio_async_io_read_write_benchmark(black_box(file_size)))
    });

    // c.bench_function("glommio write_read", |b| {
    //     b.iter(|| glommio_write_read(black_box(file_size)))
    // });
}

criterion_group!(benches, benchmark);
criterion_main!(benches);